/*
 * Vector.c
 *
 * 描述: 尝试使用C语言实现一个自动扩容的数据类型，并且尽量做到类似C++或者Java的封装形式。
 * 
 * --------------------------------------------------------------------------
 *
 *      Copyright (c) 2021 LiuBingyi
 *      SimpleMark is licensed under Mulan PubL v2.
 *      You can use this software according to the terms and conditions of the Mulan PubL v2.
 *      You may obtain a copy of Mulan PubL v2 at:
 *               http://license.coscl.org.cn/MulanPubL-2.0
 *      THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 *      EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 *      MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 *      See the Mulan PubL v2 for more details.
 * 
 */

/**
 *  本文档包含Vector的主要代码,所有应该公开的函数都已经包含在已初始化的结构体`vector_Method`之中，
 *  设计上应该通过这个外部变量内包含的函数指针来调用所需的函数，而不应该直接调用。
 * 
 *  目前所包含的函数尚不够完善，从面向对象的思想来说。封装的不是很完善，仍有一些功能待提供。
 * 
 * author:LiuBingyi
 * email:cecillearofa@163.com
 * time:2021-7-21 1:05
 */

#ifndef _EXPORTING
#define _EXPORTING
#endif
#include "Vector.h"

#define cast_void(voidPrt) ((char*)voidPrt)
#define vectorTail(this) (cast_void(this->container) + (this->elementSize * (this->elementCount - 1)))
#define vectorNext(this) (cast_void(this->container) + this->elementSize * this->elementCount)
#define vectorIndex(this, index) (cast_void(this->container) + this->elementSize * index)
#define vectorSizeOf(this, index) ((this->elementCount - index) * this->elementSize)

Vector vectorConstructor(size_vector capacity, size_vector increment, memSize elementSize);
constElementObj vectorContainer(Vector this);
int addElement(Vector this, constElementObj obj);
int insertElement(Vector this, constElementObj obj, size_vector index);
int eraseElement(Vector this, size_vector index);
int subElement(Vector this);
int placeElement(Vector this, constElementObj obj, size_vector index);
//int removeElement(Vector this, size_vector index);
size_vector indexOf(Vector this, constElementObj obj);
constElementObj elementAt(Vector this, size_vector index);
int sortElement(Vector this, void(*rule));
int removeElement(Vector this);
int removeMultipleElement(Vector this, size_vector rmCount);
size_vector length(Vector this);
int vectorClose(Vector this);

DLLDECLSPEC const struct VectorMethod vector_Method = {
    vectorConstructor,
    vectorContainer,
    addElement,
    insertElement,
    eraseElement,
    subElement,
    placeElement,
    indexOf,
    elementAt,
    sortElement,
    removeElement,
    removeMultipleElement,
    length,
    vectorClose
};

Vector stack = NULL; //计划维护一个包含所有外部Vector的Vector以实现自动管理,避免内存泄漏。

/* Vector内部的函数，所有对Vector进行增量`操作`的入口 */
int increase(Vector i, size_vector increment)
{
    size_vector needLength = i->elementCount + increment;
    size_vector finalLength = i->capacity;
    int returnValue = 0;
    if (finalLength <= needLength) {
        while ((finalLength += i->capacityIncrement) <= needLength) { }

        elementObj buffer = (elementObj)memoryApply(finalLength, i->elementSize);
        if (buffer) {
            memoryCopy(buffer, i->container, i->capacity * i->elementSize);
            memoryDelete(i->container);
            i->container = buffer;
            i->capacity = finalLength;
        } else {
            returnValue = -1;
        }
    }
    return returnValue;
}
/* Vector内部的函数，所有对Vector进行`缩减`操作的入口 */
int decrease(Vector d, size_vector increment)
{
    size_vector needLength = d->elementCount - increment;
    size_vector finalLength = d->elementCount - d->capacityIncrement;
    int returnValue = 0;
    if (needLength < finalLength && needLength > (d->capacity - d->elementCount * d->capacityIncrement)) {
        while ((finalLength -= d->capacityIncrement) >= needLength) { }

        elementObj buffer = (elementObj)memoryApply(finalLength, d->elementSize);
        if (buffer) {
            memoryCopy(buffer, d->container, finalLength);
            memoryDelete(d->container);
            d->container = buffer;
            d->capacity = finalLength;
        } else {
            returnValue = -1;
        }
    }
    return returnValue;
}

Vector vectorConstructor(
    size_vector capacity,
    size_vector increment,
    memSize elementSize)
{
    Vector this = (Vector)memoryApply(sizeof(vectorBase), 1);
    this->container = memoryApply(capacity, elementSize);
    this->capacity = capacity;
    this->capacityIncrement = increment;
    this->elementCount = 0UL;
    this->elementSize = elementSize;
    return this;
}

constElementObj vectorContainer(Vector this)
{
    return this->container;
}

int addElement(Vector this, constElementObj obj)
{
    int rtn = increase(this, 1);
    if (!rtn) {
        elementObj tail = vectorNext(this);
        memoryCopy(tail, obj, this->elementSize);
        this->elementCount++;
    }
    return rtn;
}

int insertElement(Vector this, constElementObj obj, size_vector index)
{
    int rtn = increase(this, 1);
    if (!rtn) {
        elementObj dest = vectorIndex(this, index);
        memoryMove(dest + this->elementSize, dest, vectorSizeOf(this, index));
        memoryCopy(dest, obj, this->elementSize);
        this->elementCount++;
    }
    return rtn;
}

int eraseElement(Vector this, size_vector index)
{
    elementObj dest = vectorIndex(this, index);
    memoryMove(dest, dest + this->elementSize, vectorSizeOf(this, index) - 1);
    return 0;
}

int subElement(Vector this)
{
    elementObj dest = vectorTail(this);
    memoryClear(dest, this->elementSize);
    this->elementCount--;
    return 0;
}

int placeElement(Vector this, constElementObj obj, size_vector index)
{
    elementObj dest = vectorIndex(this, index);
    memoryCopy(dest, obj, this->elementSize);
    return 0;
}

size_vector indexOf(Vector this, constElementObj obj)
{
    for (size_vector i = 0; i < this->elementCount; i++) {
        for (size_vector j = 0; j < this->elementSize; j++) {
            if (*(cast_void(obj) + j) ^ *vectorIndex(this, i + j)) {
                break;
            } else if (j == this->elementSize - 1) {
                return i;
            }
        }
    }

    return -1;
}

constElementObj elementAt(Vector this, size_vector index)
{
    return index >= this->elementCount ? NULL : vectorIndex(this, index);
}

size_vector length(Vector this)
{
    return this->elementCount;
}

int sortElement(Vector this, void(*rule)) { return 0; }
//与subelement不同的是，如果删除后剩余的数量减少到临界线，这个函数会对Vector的内存进行缩减。
int removeElement(Vector this)
{
    subElement(this);
    decrease(this, 1);
    return 0;
}
//一次性删除多个元素，如果删除后剩余的元素数量减少到临界线，这个函数会对Vector的内存进行缩减。
int removeMultipleElement(Vector this, size_vector rmCount)
{
    size_vector finish = this->capacity;
    decrease(this, rmCount < finish ? rmCount : finish);
    return 0;
}
//待完成
int vectorCopy(Vector dest, Vector src)
{
    return 0;
}

int vectorClose(Vector this)
{
    memoryDelete(this->container);
    memoryDelete(this);
    return 0;
}

//待完成
int freeAllVector() { return 0; }
